package main

import "fmt"

func main() {
	//切片三要素： 指针   长度   容量
	//切片埠村支，它就像一个框，去底层数组框值
	//1.切片（Slice）
	var s1 []int //没有分配内存，==nil
	fmt.Println(s1)
	fmt.Println(s1 == nil)
	//1.赋值初始化，分配内存
	s1 = []int{1, 2, 3}
	fmt.Println(s1)
	//2.make 初始化，分配内存
	s2 := make([]bool, 2, 4)
	fmt.Println(s2)
	s3 := make([]int, 0, 4)
	fmt.Println(s3 == nil) //分配了内存，!=nil

	s4 := []int{1, 2, 3}
	s5 := s4
	fmt.Println(s5)
	s5[1] = 200
	//[1 200 3]
	fmt.Println(s5)
	fmt.Println(s4)

	//切片的扩容策略
	/* 	1.如果申请的策略大于原来的两倍，那么就直接扩容至新申请的容量
	   	2.如果小于1024，那么直接两倍
	   	3.如果大于1024，就按照1.25倍扩容
	   	4.具体存储的值类型不同，扩容策略也有所不同 */

	//以下两种方式，两种初始化分配内存分配方法   make   append
	var s6 []int        //nil,需要初始化
	s6 = make([]int, 1) //初始化分配内存
	s6[0] = 1
	fmt.Println(s6)

	var s7 []int
	s7 = append(s7, 10, 20, 30) //append自动初始化切片，分配内存
	fmt.Println(s7)

	s8 := []int{1, 4, 3}
	s9 := s8
	var s10 []int //需要初始化,分配内存
	s11 := make([]int, 4)
	fmt.Println(s9)
	copy(s10, s9)
	copy(s11, s9)
	s9[1] = 200
	//[1 200 3]
	fmt.Println(s8)
	fmt.Println(s9)
	fmt.Println(s10)
	fmt.Println(s11)

	//数组
	var name string
	name = "lixiang"
	fmt.Println(name)
	//1.先声明，再初始化
	var ages1 [30]int //声明一个变量ages，它是[30]int类型
	ages1 = [30]int{1, 2, 3, 4, 6}
	fmt.Println(ages1)
	//2.直接初始化
	var ages2 = [10]int{1, 2, 3}
	fmt.Println(ages2)
	var ages3 = [...]int{1, 2, 3, 6, 7, 8} //可无限扩充
	fmt.Println(ages3)
	//3.索引赋值初始化
	var ages4 = [...]int{1: 100, 5: 30}
	fmt.Println(ages4)

	//二维数组

	var a1 [3][2]int //
	a1 = [3][2]int{
		[2]int{1, 2},
		[2]int{3, 4},
		[2]int{5, 6},
	}
	fmt.Println(a1)

	//多维数组只有最外层可以使用...
	var a2 = [...][2]int{
		[2]int{1, 2},
		[2]int{3, 4},
		[2]int{5, 6},
	}
	fmt.Println(a2)

	x := [3]int{1, 2, 3}
	y := x
	y[1] = 200
	fmt.Printf("x=%v \n", x)
	fmt.Printf("y=%v \n", y)
	f1(x)
	fmt.Printf("值传递后x=%v \n", x)

	fmt.Printf("x===%T---%v \n", x, x)
	fmt.Printf("&x===%T---%v \n", &x, &x)
	f2(&x)
	fmt.Printf("引用传递数组后x=%v \n", x)

	fmt.Printf("x[1]===%T---%v \n", x[1], x[1])
	fmt.Printf("&x[1]===%T---%v \n", &x[1], &x[1])
	f3(&x[1])
	fmt.Printf("引用传递数组单值后x=%v \n", x)

	addr := "沙河"
	addrP := &addr //内存地址
	fmt.Printf("addrP===%T---%v \n", addrP, addrP)

	addrV := *addrP //根据内存地址找值
	fmt.Printf("addrV===%T---%v \n", addrV, addrV)

	//map
	var m1 map[string]int
	fmt.Println(m1)
	fmt.Println(m1 == nil)
	//1.make初始化分配内存
	m1 = make(map[string]int, 10)
	m1["lianxiang"] = 100
	fmt.Println(m1)
	fmt.Println(m1["ji"]) //如果key不存在，返回的是对应类型的零值
	//m1["ji"] = 0   //临界值
	//如果返回值是布尔类型，我们通常用OK接收它
	score, ok := (m1["ji"])
	if !ok {
		fmt.Println("没有这个key值")
	} else {
		fmt.Println(score)
	}

	delete(m1, "lixiang") //删除的key不存在，什么都不干
	delete(m1, "lianxiang")
	fmt.Println(m1)
	fmt.Println(m1 == nil) //已经开辟内存，!=nil
}

//值传递
func f1(a [3]int) {
	//Go语言中的函数传递的都是值ctrl+c    ctrl+v
	a[1] = 100
	fmt.Printf("函数中值传递a=%v \n", a) //此处修改的是副本的值
}

//引用传递数组
func f2(a *[3]int) {
	//Go语言中的函数传递的都是值ctrl+c    ctrl+v
	a[1] = 200
	fmt.Printf("函数中引用传递数组a=%v \n", a)
}

func f3(a *int) {
	//Go语言中的函数传递的都是值ctrl+c    ctrl+v
	*a = 300
	fmt.Printf("函数中引用传递数组单值a=%v \n", *a)
}
